package ginext

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"gopkg.in/go-playground/validator.v8"
)

// 验证并处理，如果验证失败则直接返回400错误与相关字段的错误信息
// 例：
//		type user struct {
//			Username string `form:"username" binding:"required,max=40"`
//		}
//
//		r.POST("/users", VHandle(&user{}, func (obj interface{}, c *gin.Context) {
//			u := obj.(*user)
//			c.String(http.StatusOK, u.Username)
//		}))
func VHandle(obj interface{}, handler func(obj interface{}, c *gin.Context)) gin.HandlerFunc {
	return func(c *gin.Context) {
		if err := c.Bind(obj); err != nil {
			// 验证错误处理
			if errors, ok := err.(validator.ValidationErrors); ok {
				errMsg := make(gin.H, len(errors))

				// 构造验证错误信息
				for _, v := range errors {
					// 默认字段为小写
					errMsg[strings.ToLower(v.Field)] = gin.H{
						"type":  v.Type.Name(),
						"tag":   v.Tag,
						"param": v.Param,
						"value": v.Value,
					}
				}

				c.JSON(http.StatusBadRequest, gin.H{
					"error": errMsg,
				})
				return
			}

			// 非验证错误处理
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
			return
		}

		// 调用自定义的处理函数
		handler(obj, c)
	}
}
